const fs = require("fs");
const path = require("path");
const glob = require("glob");
const lodash = require("lodash");
const util = require("util");

/**
 * 
 * @param {String} full_path 确定是有效路径 
 * @return {Promise<{size:Number,ok:Boolean,msg:String}>}
 */
function getFileSize(full_path) {
  return new Promise(resolve => {
    fs.stat(full_path, (error, stats) => {
      if (error) {
        return resolve({ ok: false, msg: error.message, size: 0 })
      }
      return resolve({
        ok: true,
        size: stats.size
      })
    })
  })
}

/**
 * 
 * @param {String} full_path 
 * @returns {Promise<{exists:Boolean}>}
 */
function checkExist(full_path) {
  return new Promise(resolve => {
    fs.exists(path, (exists) => {
      resolve({ exists: exists })
    })
  })
}

/**
 * 
 * @param {String} full_path  确定是有效路径 
 * @returns {Promise<{ok:Boolean,msg:String,isFile:Boolean}>}
 */
function checkIsFile(full_path){
  return new Promise(resolve=>{
    fs.stat(full_path,(err,stats)=>{
      if(err){
        return resolve({
          ok:false,
          msg:err.message,
          isFile:false
        })
      }
      return resolve({
        ok:true,
        msg:"ok",
        isFile:stats.isFile()
      })
    })    
  })
}

/**
 * 
 * @param {String[]} args_subs 
 * @param {String} cwd
 * @returns {Promise<{good_path_matches:String[]}>}
 */
function getFileList(args_subs, cwd) {
  let find_files_by_glob = args_subs.map(
    /**
     * @returns {Promise<String[]>}
     */
    p => new Promise(
      (resolve, reject) => {
        glob(p, (err, matches) => {
          if (err) {
            return reject(err);
          }
          resolve(matches);
        })
      }));
  let find_files_by_raw = args_subs.map(
    /**
      * @returns {Promise<String[]>}
      */
    p => new Promise((resolve, reject) => {
      if (path.isAbsolute(p)) {
        resolve([path.resolve(p)])
      } else {
        resolve([path, resolve(cwd, p)])
      }
    }));
  return new Promise(resolve => {
    Promise.all([...find_files_by_glob, ...find_files_by_raw])
      .then(([...macthes]) => {
        let ms = lodash.union(...macthes.map(e => e.map(ele => path.resolve(cwd, ele))));
        let os_checkExist = await Promise.all(ms.map(p=>checkExist(p)));
        ms = ms.filter((path_value,index)=>{
          return os_checkExist[index].exists;
        });
        let os_checkIsFile = await Promise.all(ms.map(p=>checkIsFile(p)));
        let not_ok_checkIsFile = os_checkIsFile.filter(o=>!o.ok);
        if(not_ok_checkIsFile.length){
          console.error("Some path checkIsFile failed!");
          console.error(util.inspect(not_ok_checkIsFile));
        }
        ms = ms.filter((path_value,index)=>{
          return os_checkIsFile[index].ok && os_checkIsFile[index].isFile;
        });
        resolve({good_path_matches:ms});
      })
  });
}


module.exports = {
  getFileSize,
  checkExist,
  getFileList
}